package com.ht.config.security;

import com.ht.config.security.handler.*;
import com.ht.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @ProjectName: ht
 * @ClassName: SecurityConfig
 * @Author: hejialun
 * @Description: security配置类
 * @Date: 2021/6/22 11:56
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    LocalAuthenticationEntryPointHandler authenticationEntryPoint;//未登陆时返回 JSON 格式的数据给前端（否则为 html）
    @Autowired
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private LocalAuthenticationSuccessHandler localAuthenticationSuccessHandler;    //登录成功处理
    @Autowired
    private LocalAuthenticationFailureHandler localAuthenticationFailureHandler;    //登录失败处理
    @Autowired
    private LocalAccessDeniedHandler localAccessDeniedHandler;    //无权访问处理
    @Autowired
    private LocalLogoutSuccessHandler localLogoutSuccessHandler;    //退出登录

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;  //jwt过滤器
    @Autowired
    private DataSource dataSource;      //数据源

    /*配置对象-实现记住我功能*/
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(true);      //自动生成记住我表
        return jdbcTokenRepository;
    }




    /**
     * 注入加密对象
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * 完成security设置
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 去掉 CSRF
        http.cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 使用 JWT，关闭token
                .and()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .formLogin()  //开启登录, 定义当需要用户登录时候，转到的登录页面
//                .loginPage("/test/login.html")
//                .loginProcessingUrl("/login")
                .successHandler(localAuthenticationSuccessHandler) // 登录成功
                .failureHandler(localAuthenticationFailureHandler) // 登录失败
                .permitAll()
                .and()
                .authorizeRequests()//定义哪些URL需要被保护、哪些不需要被保护
                .antMatchers(
                        "/css/**",
                        "/component/**",
                        "/lib/**",
                        "/core/**",
                        "/img/**",
                        "/login.html",
                        /*放开swagger*/
                        "swagger/**",
                        "/swagger-ui.html",
                        "swagger-ui.html",
                        "/webjars/**",
                        "/swagger-ui.html/*",
                        "/swagger-resources",
                        "/swagger-resources/**",
                        "/csrf",
                        "/v2/**",
                        "/socketServer/**",
                        "/**/getItem/**",
                        "/dingding/**",
                        "/weixin/**",
                        "/wxlogin.html",
                        "/onlyOffice.html",
                        "/imgView.html",
                        "/sys-login/login",
                        "/sys-login/getCode",
                        "/sys-login/getEmailCode/**",
                        "/sys-login/register"
                ).permitAll()       //定义不需要认证的路径//允许匿名注册
                .anyRequest().authenticated()//任何请求,登录后可以访问
                .and().rememberMe().tokenRepository(persistentTokenRepository())        //实现记住我
                .tokenValiditySeconds(60)                                               //设置记住我有效时长
                .userDetailsService(myUserDetailsService)                                 //配置查询的service
                .rememberMeParameter("rememberMe")                                      //配置记住我参数
                .rememberMeCookieName("rememberMe-cookie")                             //cookie名称

                .and()
                .logout()//默认注销行为为logout
                .logoutUrl("/logout")
                .logoutSuccessHandler(localLogoutSuccessHandler)
                .permitAll();

        http.exceptionHandling().authenticationEntryPoint(localAccessDeniedHandler); // 无权访问 JSON 格式的数据
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // JWT Filter
    }
}